package xyz.luxiaoxiang.service;

import org.apache.http.Consts;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import xyz.luxiaoxiang.bean.ChildTopic;
import xyz.luxiaoxiang.bean.HotQuestion;
import xyz.luxiaoxiang.bean.MainTopic;
import xyz.luxiaoxiang.dao.ArticleDao;
import xyz.luxiaoxiang.dao.ChildTopicDao;
import xyz.luxiaoxiang.dao.HotQuestionDao;
import xyz.luxiaoxiang.dao.MainTopicDao;
import xyz.luxiaoxiang.util.Utils;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.concurrent.Executors.newFixedThreadPool;

/**
 * @author luxx
 */
@Service
public class TopicService {

    public static Set<Integer> child_topic_set = new HashSet<>();

    /**
     * 刷新主话题
     */
    public List<MainTopic> refreshMainTopic() {
        List<MainTopic> mainTopicList = new ArrayList<>();
        try {
            URL url = new URL("https://www.zhihu.com/topics");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.connect();
            BufferedReader bfr = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while ((line = (bfr.readLine())) != null) {
                sb.append(line);
            }
            String result = sb.toString();
            String regex = "data-id=\"[0-9]{0,6}\"";
            Pattern pattern = Pattern.compile(regex);
            //返回matcher
            Matcher m = pattern.matcher(result);
            String regx = "href=\"#.*?\"";
            Pattern p = Pattern.compile(regx);
            Matcher mn = p.matcher(result);
            //通过m.find()来查找,找到一个返回true,找不到就返回false, m.group()要与find()结合才能找到结果集
            while (m.find() && mn.find()) {
                String s = m.group();
                //data-id="19800"><a href="#金融">金融</a>
                s = s.substring(9, s.length() - 1);
                String sn = mn.group();
                sn = sn.substring(7, sn.length() - 1);
                MainTopic mainTopic = new MainTopic(Integer.valueOf(s), sn);
                mainTopicDao.save(mainTopic);
                mainTopicList.add(mainTopic);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mainTopicList;
    }

    /**
     * 获取所有主话题
     */
    public List<MainTopic> getMainTopic() {
        try {
            return mainTopicDao.findAll();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取所有字话题
     */
    public List<ChildTopic> getChildTopic() {
        try {
            return childTopicDao.findAll();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取一个主话题下的所有字话题
     */
    public List<ChildTopic> getChildTopic(int mainTopicId) {
        try {
            return childTopicDao.findAllByMainTopicId(mainTopicId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 刷新所有子话题
     */
    public void refreshChildTopic() {
        List<Integer> list = new ArrayList<>();
        ExecutorService exec = newFixedThreadPool(2);
        List<MainTopic> topics = mainTopicDao.findAll();
        for (MainTopic topic : topics) {
            list.add(topic.getMainTopicId());
        }
        //通过线程池开启新线程获取数据
        for (int i = 0; i < list.size(); i++) {
            int main_topic_id = list.get(i);
            exec.execute(() -> {
                try {
                    refreshChildTopic(main_topic_id);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        exec.shutdown();
    }

    /**
     * 通过一个主话题刷新下属子话题
     *
     * @param mainTopicId
     * @throws Exception
     */
    public List<ChildTopic> refreshChildTopic(int mainTopicId) {
        try {
            List<ChildTopic> childTopicList = new ArrayList<>();
            int offset = 0;
            while (true) {
                PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
                CloseableHttpClient httpClient = HttpClients.custom()
                        .setRetryHandler(new DefaultHttpRequestRetryHandler())
                        .setConnectionManager(cm)
                        .build();
                HttpPost req = new HttpPost("https://www.zhihu.com/node/TopicsPlazzaListV2");
                List<NameValuePair> params = new ArrayList<NameValuePair>();
                params.add(new BasicNameValuePair("method", "next"));
                params.add(new BasicNameValuePair("params", "{\"topic_id\":" + mainTopicId + ",\"offset\":" + offset + ",\"hash_id\":\"37492588249aa9b50ee49d1797e9af81\"}"));
                req.setEntity(new UrlEncodedFormEntity(params, Consts.UTF_8));
                HttpResponse resp = httpClient.execute(req);
                String sb = EntityUtils.toString(resp.getEntity());
                if (sb.length() < 25) {
                    break;
                }
                //<strong>世界电子竞技大赛 (WCG)</strong>
                //.是单个任意字符*是任意多个,通过?采取非贪婪模式，否则贪婪模式会直接匹配到最后一个
                //href=\"/topic/19550994\"
                String regex = "<strong>.*?<\\\\/strong>";
                Pattern p = Pattern.compile(regex);
                Matcher m = p.matcher(sb);
                String regx = "href=\\\\\"\\\\/topic\\\\/[0-9]+\\\\\"";
                Pattern p1 = Pattern.compile(regx);
                Matcher m1 = p1.matcher(sb);
                while (m.find() && m1.find()) {
                    String temp = m.group().substring(8, m.group().length() - 10);
                    ChildTopic childTopic = new ChildTopic(mainTopicId,
                            Integer.parseInt(m1.group().substring(16, m1.group().length() - 2)),
                            Utils.decodeUnicode(temp));
                    childTopicList.add(childTopic);
                }
                offset += 20;
            }
            for (ChildTopic childTopic : childTopicList) {
                childTopicDao.save(childTopic);
            }
            return childTopicList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取所有热门问答(从远程)
     */
    public List<HotQuestion> getHotQuestionRemote() {
        List<HotQuestion> hotQuestionList = new ArrayList<>();
        ExecutorService exec = newFixedThreadPool(2);
        List<ChildTopic> topics = childTopicDao.findAll();
        for (ChildTopic topic : topics) {
            synchronized (child_topic_set) {
                //锁住是为了防止多线程时同时判断重复进入if代码块
                Integer childTopicId = topic.getChildTopicId();
                if (!child_topic_set.contains(childTopicId)) {
                    child_topic_set.add(childTopicId);
                    exec.execute(() -> {
                        try {
                            List<HotQuestion> singleHotQuestionList = getHotQuestionRemote(childTopicId);
                            for (HotQuestion hotQuestion : singleHotQuestionList) {
                                hotQuestionList.add(hotQuestion);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    });
                }
            }
        }
        exec.shutdown();
        child_topic_set.clear();
        return hotQuestionList;
    }

    /**
     * 获取所有热门问答(从本地)
     */
    public List<HotQuestion> getHotQuestion() {
        try {
            return hotQuestionDao.findAll();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 刷新单个话题下的热门问答
     *
     * @param childTopicId
     */
    public List<HotQuestion> getHotQuestionRemote(int childTopicId) {
        LoadDetailInformationService loadDetailInformation = new LoadDetailInformationService();
        List<HotQuestion> hotQuestionList = new ArrayList<>();
        try {
            hotQuestionList = loadDetailInformation.loadNHotQA(5, String.valueOf(childTopicId));
            for (HotQuestion qa : hotQuestionList) {
                if (qa.isArticle()) {
                    articleDao.save(qa.getHotArticle());
                } else {
                    hotQuestionDao.save(qa);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return hotQuestionList;
    }

    /**
     * 获取单个话题下的热门问答
     *
     * @param childTopicId
     */
    public List<HotQuestion> getHotQuestion(int childTopicId) {
        try {
            return hotQuestionDao.findAllByChildTopicId(childTopicId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Autowired
    private HotQuestionDao hotQuestionDao;
    @Autowired
    private ArticleDao articleDao;
    @Autowired
    private MainTopicDao mainTopicDao;
    @Autowired
    private ChildTopicDao childTopicDao;
}
